package com.xiyang.web.controller;

import com.xiyang.common.entity.Permission;
import com.xiyang.common.entity.Role;
import com.xiyang.common.entity.User;
import com.xiyang.common.repository.PermissionRepository;
import com.xiyang.common.repository.RoleRepository;
import com.xiyang.common.repository.UserRepository;
import com.xiyang.common.response.BaseResult;
import com.xiyang.common.response.ReturnCode;
import com.xiyang.web.configuration.security.authorization.CustomInvocationSecurityMetadataSourceService;
import com.xiyang.web.utils.SecurityUtil;
import com.xiyang.web.vo.UserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @author xiyang.ycj
 * @since Jul 19, 2019 14:03:12 PM
 */
@Controller
@RequestMapping(value = "/admin")
public class AdminController {

    private static final Logger log = LoggerFactory.getLogger(AdminController.class);

    private final RoleRepository roleRepository;
    private final PermissionRepository permissionRepository;
    private final UserRepository userRepository;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final CustomInvocationSecurityMetadataSourceService customInvocationSecurityMetadataSourceService;

    public AdminController(RoleRepository roleRepository, PermissionRepository permissionRepository, UserRepository userRepository, BCryptPasswordEncoder bCryptPasswordEncoder, CustomInvocationSecurityMetadataSourceService customInvocationSecurityMetadataSourceService) {
        this.roleRepository = roleRepository;
        this.permissionRepository = permissionRepository;
        this.userRepository = userRepository;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.customInvocationSecurityMetadataSourceService = customInvocationSecurityMetadataSourceService;
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(ModelMap map) {
        map.put("userId", SecurityUtil.getSecurityUser().getId());
        return "admin/index";
    }

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public String register(ModelMap map) {
        map.put("roles",roleRepository.findAll());
        return "admin/register";
    }




    @GetMapping(value = "/allUserInfo",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ResponseBody
    public Object allUserInfo(@RequestParam(required = false,defaultValue = "0") int page,@RequestParam(required = false,defaultValue = "10") int limit,ModelMap model){
        try {

            Pageable pageable = PageRequest.of(page-1, limit, new Sort(Sort.Direction.ASC, "id"));
            Page<User> pddBuyers = userRepository.findAll(pageable);
            model.put("rows",  pddBuyers.getContent());
            model.put("total", pddBuyers.getTotalElements());
            return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage(), model);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new BaseResult(ReturnCode.FAILED.getCode(),ReturnCode.FAILED.getMessage());
    }

    @PostMapping(value = "/deleteUser",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Object deleteUser(@RequestBody UserVO userVO){
        log.info("待删除账户信息:{}",userVO);
        try {
            userRepository.deleteById(userVO.getUserId());
            return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage());
        } catch (Exception e) {
            e.printStackTrace();

        }
        return new BaseResult(ReturnCode.FAILED.getCode(),ReturnCode.FAILED.getMessage());
    }

    @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
    @ResponseBody
    public Object getUserInfo(@RequestParam("username")String username) {
        if(userRepository.findUserByAccount(username).isPresent()){
            return new BaseResult(ReturnCode.FAILED.getCode(),"账户已存在");
        }
        return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage());
    }


    @PostMapping(value = "/addUser",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Object addUser(@RequestBody UserVO userVO){
        log.info("添加账户:{}",userVO.toString());
        try {
            User user = new User();
            BeanUtils.copyProperties(userVO, user);
            Set<Role> roles = new HashSet<>();
            roles.add(roleRepository.findByRoleCode(userVO.getRole()));
            user.setRoles(roles);
            user.setPassword(bCryptPasswordEncoder.encode(userVO.getPassword()));
            log.info("添加账户信息:{}",user.toString());
            return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage(),userRepository.saveAndFlush(user));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new BaseResult(ReturnCode.FAILED.getCode(),ReturnCode.FAILED.getMessage());
    }


    @GetMapping(value = "/loadPage",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ResponseBody
    public Object loadPage(@RequestParam(required = false,defaultValue = "0") int page,@RequestParam(required = false,defaultValue = "10") int limit,ModelMap model){
        try {

            Pageable pageable = PageRequest.of(page-1, limit, new Sort(Sort.Direction.ASC, "roleId"));
            Page<Role> roles = roleRepository.findAll(pageable);
            model.put("rows",  roles.getContent());
            model.put("total", roles.getTotalElements());
            return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage(), model);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new BaseResult(ReturnCode.FAILED.getCode(),ReturnCode.FAILED.getMessage());
    }


    @GetMapping(value = "/getNoPermission",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ResponseBody
    public Object getNoPermission(@RequestParam(required = false,defaultValue = "0") int page,@RequestParam(required = false,defaultValue = "10") int limit,@RequestParam("roleId") Integer roleId,ModelMap model){
        try {
            Role role = roleRepository.findById(roleId).get();
            HashSet<Role> set = new HashSet<>();
                set.add(role);
            List<Permission> permissions = permissionRepository.findAllByRoles(set);
            List<Permission> permissionList = permissionRepository.findAll();
            Iterator<Permission> iterator = permissionList.iterator();
            while(iterator.hasNext()) {
                Permission permission = iterator.next();
                if(permissions.size()>0)
                for (Permission p : permissions) {
                    if (permission.getId().equals(p.getId()))iterator.remove();
                }
            }
            model.put("rows",  permissionList);
            model.put("total", permissionList.size());
            return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage(), model);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new BaseResult(ReturnCode.FAILED.getCode(),ReturnCode.FAILED.getMessage());
    }


    @PostMapping(value = "/addRole",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ResponseBody
    public Object add(@RequestParam("roleName") String roleName,@RequestParam String roleCode){
        Role role = new Role();
        role.setRoleName(roleName);
        role.setRoleCode(roleCode);
        roleRepository.saveAndFlush(role);
        return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage());
    }

    @PostMapping(value = "/edit",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ResponseBody
    public Object edit(@RequestParam("roleId") Integer roleId,@RequestParam("ids")Integer[] ids){
        Set<Permission> permissions = permissionRepository.findAllByIdIn(Arrays.asList(ids));
        Role role = roleRepository.findById(roleId).get();
        Set<Permission> permissionSet = role.getPermissions();
        permissionSet.addAll(permissions);
        role.setPermissions(permissionSet);
        roleRepository.saveAndFlush(role);

        customInvocationSecurityMetadataSourceService.init();

        return new BaseResult(ReturnCode.SUCCESS.getCode(),ReturnCode.SUCCESS.getMessage());
    }

}
